import { _decorator, Animation, Collider2D, EventTouch, Input, input, IPhysics2DContact, Node, Prefab, Vec2 } from 'cc';
import Biz from '../../biz';
import { MaxHeight, MaxWidth } from '../../consts';
import { EventName } from '../../consts/events';
import { AudioPath } from '../../consts/resources';
import Utils from '../../utils';
import { BulletType } from '../config/bullet';
import { createBullet } from './bullet';
import { AbstractEntity, RoleAnimation } from './common';
const { ccclass } = _decorator;

@ccclass('Player')
export class Player extends AbstractEntity {
    private roleAnima = new RoleAnimation();
    public init(name: string) {
        if (this.isInit) return;
        this.isInit = true;
        this.roleName = name;
        this.roleAnima.init(Utils.tools.upperFirstLetter(name));
        input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
        Utils.events.on(EventName.StartGame, this.onStartGame, this); // 开始游戏
        Utils.events.on(EventName.PauseGame, this.onPauseGame, this); // 暂停游戏
        Utils.events.on(EventName.ResumeGame, this.onResumeGame, this); // 继续游戏
        Utils.events.on(EventName.PlayerShoot, this.onShoot, this); // 发射子弹
        Utils.events.on(EventName.PlayerDown, this.onPlayerDown, this); // 结束游戏
        Utils.events.on(EventName.PlayerInvincible, this.onInvincible, this); // 无敌时间
    }
    protected destructor(): void {
        input.off(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
        Utils.events.off(EventName.StartGame, this.onStartGame, this);
        Utils.events.off(EventName.PauseGame, this.onPauseGame, this);
        Utils.events.off(EventName.ResumeGame, this.onResumeGame, this);
        Utils.events.off(EventName.PlayerShoot, this.onShoot, this);
        Utils.events.off(EventName.PlayerInvincible, this.onInvincible, this);
    }
    private onStartGame(): void {
        this.roleAnima.idle(this.anima);
        this.joinTheWorld();
    }
    private onPauseGame(): void {
        this.anima.stop();
    }
    private onResumeGame(): void {
        this.roleAnima.idle(this.anima);
    }
    private onPlayerDown(): void {
        this.colliderBody.enabled = false;
        this.roleAnima.dead(this.anima);
        Utils.audio.playOneShot(AudioPath.GameOver);
        this.anima.on(Animation.EventType.FINISHED, this.afterDead, this);
    }
    private onInvincible(): void {
        this.roleAnima.hit(this.anima);
    }

    public joinTheWorld(): void {
        if (this.isJoinTheWorld) return;
        this.node.active = true;
        this.sprite.color.set(255, 255, 255);
        this.isJoinTheWorld = true;
        this.colliderBody.enabled = true;
        this.node.setPosition(0, -300);
    }
    public exitTheWorld(): void {
        if (!this.isJoinTheWorld) return;
        this.isJoinTheWorld = false;
        this.colliderBody.enabled = false;
    }
    private afterDead(): void {
        this.exitTheWorld();
        this.anima.off(Animation.EventType.FINISHED, this.afterDead, this);
        Utils.events.emit(EventName.EndGame);
    }

    // 碰撞检测
    protected onPhysicsCollision(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {}

    protected update(dt: number): void {
        if (!Biz.global.isStart || !this.isJoinTheWorld || Biz.hp.isPlayerDown()) return;
    }

    private onShoot() {
        if (!Biz.global.isStart || !this.isJoinTheWorld || Biz.hp.isPlayerDown()) return;
        const pos = new Vec2(this.node.position.x, this.node.position.y);
        pos.y = pos.y + this.size.height / 2;
        createBullet(Biz.global.rootBullet, Biz.global.bullet[BulletType.BulletPlayer], pos);
        Utils.audio.playOneShot(AudioPath.Shoot);
    }

    private onTouchMove(ev: EventTouch) {
        if (!Biz.global.isStart || !this.isJoinTheWorld || Biz.hp.isPlayerDown()) return;
        const pos = this.node.position;
        let x = pos.x + ev.getDeltaX();
        let y = pos.y + ev.getDeltaY();
        if (x < -MaxWidth / 2) {
            x = -MaxWidth / 2;
        } else if (x > MaxWidth / 2) {
            x = MaxWidth / 2;
        }
        if (y < -MaxHeight / 2) {
            y = -MaxHeight / 2;
        } else if (y > MaxHeight / 2) {
            y = MaxHeight / 2;
        }
        this.node.setPosition(x, y);
    }
}

export const createPlayer = (root: Node, prefab: Prefab): Player => {
    const body = Utils.pool.createNode(prefab);
    body.setParent(root);
    let entity = body.getComponent(Player);
    if (!entity) {
        entity = body.addComponent(Player);
        entity.init(prefab.name);
    }
    entity.joinTheWorld();
    return entity;
};
